/* 
* Copyright (c) Harry Pierson. 
*
* This source code is subject to terms and conditions of the Microsoft 
* Permissive License. A copy of the license can be found in the License.html 
* file at the root of this distribution. If you cannot locate the  Microsoft 
* Permissive License, please send an email to harry@devhawk.net. By using this 
* source code in any fashion, you are agreeing to be bound by the terms of the 
* Microsoft Permissive License.
* 
* You must not remove this notice, or any other, from this software.
*/

using System;
using System.IO;

namespace HawkWiki.WikiRenderer
{
    public abstract class WikiWriter
    {
        public enum ListType
        {
            Bulleted,
            Numbered
        }

        #region WikiWordExist and WikiWordLink delegates
        public delegate bool WikiWordExistsDelegate(string wikiWord);

        protected WikiWordExistsDelegate _wikiWordExists = null;

        public WikiWordExistsDelegate WikiWordExists
        {
            get { return _wikiWordExists; }
            set { _wikiWordExists = value; }
        }

        protected bool GetWikiWordExist(string wikiWord)
        {
            if (WikiWordExists == null)
                return false;

            return WikiWordExists(wikiWord);
        }

        public delegate string WikiWordLinkDelegate(string wikiWord);

        protected WikiWordLinkDelegate _wikiWordLink = null;

        public WikiWordLinkDelegate WikiWordLink
        {
            get { return _wikiWordLink; }
            set { _wikiWordLink = value; }
        }

        protected string GetWikiWordLink(string wikiWord)
        {
            if (WikiWordLink == null)
                return string.Empty;

            return WikiWordLink(wikiWord);
        }
        #endregion


        public abstract void WriteText(string text);
        public abstract void WriteWikiWord(string text);
        public abstract void WriteHyperlink(string url, string text);
        public abstract void WriteImage(string url);
        public abstract void WriteFootnote(string text);
        public abstract void WriteFootnoteLink(string text);
        public abstract void WriteRule();
        public abstract void WriteNewline();

        public abstract void WriteBold(bool start);
        public abstract void WriteItalics(bool start);
        public abstract void WriteParagraph(bool start);
        public abstract void WriteListItem(bool start);
        public abstract void WriteMonospaced(bool start);
        public abstract void WriteIndent(bool start);
        public abstract void WriteList(ListType type, bool start);
        public abstract void WriteHeading(int level, bool start);
    }

    public class HtmlWikiWriter : WikiWriter
    {
        TextWriter _tw;

        public HtmlWikiWriter(TextWriter tw)
        {
            _tw = tw;
        }

        public override void WriteText(string text)
        {
            if (text.IndexOfAny(new char[] { '&', '\"', '<', '>' }) != -1)
            {
                text = text.Replace("&", "&amp;");
                text = text.Replace("\"", "&quot;");
                text = text.Replace("<", "&lt;");
                text = text.Replace(">", "&gt;");
            }

            _tw.Write(text);

        }
        public override void WriteWikiWord(string text)
        {
            string link = GetWikiWordLink(text);
            if (link == null || link.Length == 0)
                _tw.Write(text);
            else if (GetWikiWordExist(text))
                _tw.Write("<a href='{1}'>{0}</a>", text, link);
            else
                _tw.Write("{0}<a href='{1}'>?</a>", text, link);
        }
        public override void WriteHyperlink(string url, string text) { _tw.Write("<a href='{0}'>{1}</a>", url, text); }
        public override void WriteImage(string url) { _tw.WriteLine("<img src='{0}'/>", url); }
        public override void WriteFootnote(string text) { _tw.Write("<a name='{0}'/>[{0}]", text); }
        public override void WriteFootnoteLink(string text) { _tw.Write("<a href='#{0}'>[{0}]</a>", text); }
        public override void WriteRule() { _tw.WriteLine("<hr/>"); }
        public override void WriteNewline() { _tw.WriteLine(); }
        public override void WriteBold(bool start) { WriteTag("b", start); }
        public override void WriteItalics(bool start) { WriteTag("i", start); }
        public override void WriteParagraph(bool start) { WriteTag("p", start); }
        public override void WriteListItem(bool start) { WriteTag("li", start); }
        public override void WriteMonospaced(bool start) { WriteTag("pre", start); }
        public override void WriteIndent(bool start) { WriteTag("blockquote", start); }
        public override void WriteHeading(int level, bool start) { WriteTag(string.Format("h{0}", level), start); }
        public override void WriteList(ListType type, bool start)
        {
            switch (type)
            {
                case ListType.Bulleted:
                    WriteTag("ul", start);
                    break;
                case ListType.Numbered:
                    WriteTag("ol", start);
                    break;
                default:
                    throw new ApplicationException("Invalid type passed to HtmlWikiWriter::WriteList");
            }
        }

        private void WriteTag(string tag, bool start)
        {
            if (start)
                _tw.Write("<{0}>", tag);
            else
                _tw.Write("</{0}>", tag);
        }

    }

}
